generator 是打印 AST 为目标代码,并生成 sourcemap。
这节我们实现一下 generator。
# 思路分析
generator 会遍历 AST 进行打印,对于每种 AST 我们是知道如何打印的,比如 while 语句:

先打印 while、再打印空格,再打印 ( ,然后打印 test 部分,之后打印 ),最后打印 block 部分。
那么实现了每种 AST 的打印就可以拼接出目标代码。
而 sourcemap 是记录源码位置和目标代码位置的关联,在打印的记录下当前打印的行列,就是目标代码位置,而源码位置 parse 的时候就有了,这样就生成了一个 mapping。

sourcemap 就是由一个个 mapping 组成的,打印每个 AST 节点的时候添加一下 mapping,最终就生成了 sourcemap。
# 代码实现
我们定义一个 Printer 类做打印,实现每种 AST 的打印逻辑:
class Printer {
constructor (source, fileName) {
this.buf = '';
this.printLine = 1;
this.printColumn = 0;
}
addMapping(node) {
// 待实现
}
space() {
this.buf += ' ';
this.printColumn ++;
}
nextLine() {
this.buf += '\n';
this.printLine ++;
this.printColumn = 0;
}
Program (node) {
this.addMapping(node);
node.body.forEach(item => {
this[item.type](item) + ';';
this.printColumn ++;
this.nextLine();
});
}
VariableDeclaration(node) {
if(!node.declarations.length) {
return;
}
this.addMapping(node);
this.buf += node.kind;
this.space();
node.declarations.forEach((declaration, index) => {
if (index != 0) {
this.buf += ',';
this.printColumn ++;
}
this[declaration.type](declaration);
});
this.buf += ';';
this.printColumn ++;
}
VariableDeclar